package com.pxst.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.pxst.bank.resp.BankDetailUserListResp;
import com.pxst.resp.PageResp;
import com.pxst.sys.entity.UserCurrencyEntity;
import com.pxst.sys.entity.UserRolesEntity;
import com.pxst.sys.mapper.UserCurrencyMapper;
import com.pxst.sys.resp.UserResp;
import com.pxst.sys.service.UserRolesService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pxst.exception.BusinessException;
import com.pxst.resp.ApiResp;
import com.pxst.sys.entity.UserEntity;
import com.pxst.sys.mapper.UserMapper;
import com.pxst.sys.req.UserCreateReq;
import com.pxst.sys.service.UserService;
import com.pxst.utils.BuildQueryUtils;
import org.springframework.util.StringUtils;

import javax.validation.ValidationException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author yangxy
 * @version 创建时间：2023年7月26日 下午12:41:27
 */
@Service
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> implements UserService {
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private UserCurrencyMapper userCurrencyMapper;

    @Autowired
    private UserRolesService userRolesService;

    @Autowired
    private UserMapper userMapper;

    @Override
    @SuppressWarnings("unchecked")
    public ApiResp<UserEntity> create(UserCreateReq userCreateParam) {

        QueryWrapper<UserEntity> build = BuildQueryUtils.build(UserEntity.class, userCreateParam);
//		UserEntity checkUser = getOne(new QueryWrapper<UserEntity>().lambda().eq(UserEntity::getUserName, userCreateParam.getUserName()));
        UserEntity checkUser = getOne(build);
        if (!ObjectUtils.isEmpty(checkUser)) {
            throw new BusinessException("用户名已存在");
        }
        if (StringUtils.isEmpty(userCreateParam.getPassword())) {
            throw new ValidationException("密码不能为空");
        }
        UserEntity userEntity = new UserEntity();
        BeanUtils.copyProperties(userCreateParam, userEntity);
        userEntity.setPassword(bCryptPasswordEncoder.encode(userEntity.getPassword()));
        save(userEntity);

        // 保存数据到用户币种表
        List<String> currencyList = userCreateParam.getCurrency();
        currencyList.forEach(currency -> {
            UserCurrencyEntity userCurrencyEntity = new UserCurrencyEntity();
            userCurrencyEntity.setUserId(userEntity.getId());
            userCurrencyEntity.setCurrency(currency);
            userCurrencyMapper.insert(userCurrencyEntity);
        });

        // 保存数据到权限表
        UserRolesEntity userRolesEntity = new UserRolesEntity();
        userRolesEntity.setUserId(userEntity.getId());
        userRolesEntity.setRoleId(userCreateParam.getRoleId());
        userRolesService.save(userRolesEntity);

        return ApiResp.sucess(userEntity);
    }

    @Override
    public ApiResp<UserEntity> update(Long roleId, UserCreateReq userCreateParam) {
        if (ObjectUtils.isEmpty(userCreateParam.getRoleId())) {
            throw new ValidationException("角色id不能为空");
        }
        if (ObjectUtils.isEmpty(userCreateParam.getCurrency())) {
            throw new ValidationException("币种列表不能为空");
        }
        if (ObjectUtils.isEmpty(userCreateParam.getId())) {
            throw new ValidationException("用户id不能为空");
        }
        // 更新用户表数据
        UserEntity user = getById(roleId);
        if (ObjectUtils.isEmpty(user)) {
            throw new BusinessException("用户信息不存在");
        }
        if (!StringUtils.isEmpty(user.getPassword())) {
            user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
        }
        BeanUtils.copyProperties(userCreateParam, user);
        updateById(user);

        Long userId = userCreateParam.getId();
        // 更新用户币种表信息
        userCurrencyMapper.delete(new LambdaQueryWrapper<UserCurrencyEntity>().eq(UserCurrencyEntity::getUserId, userId));
        List<String> currencyList = userCreateParam.getCurrency();
        currencyList.forEach(currency -> {
            UserCurrencyEntity userCurrencyEntity = new UserCurrencyEntity();
            userCurrencyEntity.setUserId(user.getId());
            userCurrencyEntity.setCurrency(currency);
            userCurrencyMapper.insert(userCurrencyEntity);
        });
        // 更新用户角色表信息
        userRolesService.update(null, new LambdaUpdateWrapper<UserRolesEntity>()
                .set(UserRolesEntity::getRoleId, userCreateParam.getRoleId())
                .eq(UserRolesEntity::getUserId, userId));

        return ApiResp.sucess();
    }

    @Override
    public ApiResp<PageResp<UserResp>> getAll(UserCreateReq userCreateParam) {
        Page<UserResp> userRespPage = null;
        PageHelper.startPage(userCreateParam.getPage(), userCreateParam.getRp());
        if (userCreateParam.getCurrencyUnion() == 0) {
            // 交集
            List<String> currencyList = userCreateParam.getCurrency();
            userRespPage = (Page<UserResp>) userMapper.getAllIntersection(userCreateParam, currencyList == null ? 0 : currencyList.size());
        } else {
            // 并集
            userRespPage = (Page<UserResp>) userMapper.getAllUnion(userCreateParam);
        }
        userRespPage.forEach(userResp -> {
            List<String> currency = new ArrayList<>();
            userResp.getUserCurrencyList().forEach(item -> {
                currency.add(item.getCurrency());
            });
            userResp.setCurrency(currency);
        });
        return ApiResp.page(userRespPage);
    }

    @Override
    public ApiResp<UserEntity> updateFields(Long userId, Map<String, Object> fieldsMap) {
        // 更新用户表数据
        userId = 1L;
        UserEntity user = getById(userId);
        if (ObjectUtils.isEmpty(user)) {
            throw new BusinessException("用户信息不存在");
        }
        String oldPassword = (String) fieldsMap.remove("oldPassword");
        if (!StringUtils.isEmpty(oldPassword)) {
            if (!bCryptPasswordEncoder.matches(oldPassword, user.getPassword())) {
                // 原始密码错误
                throw new BusinessException("Original password error");
            }
        }
        UpdateWrapper<UserEntity> updateWrapper = new UpdateWrapper<>();
        // 获取所有字段名
        Set<String> fields = fieldsMap.keySet();
        fields.forEach(field -> {
            updateWrapper.set(field, fieldsMap.get(field));
        });
        updateWrapper.eq("id", userId);
        update(updateWrapper);
        return ApiResp.sucess();
    }

    /**
     * 银行-详情-选择更新者下拉列表
     *
     * @return
     */
    @Override
    public ApiResp<BankDetailUserListResp> getBankLogUserNameList() {
        // 1.查询用户 id 和 username 信息
        List<BankDetailUserListResp> collect = userMapper.selectList(new LambdaQueryWrapper<UserEntity>().select(UserEntity::getId, UserEntity::getUserName))
                .stream().map(user -> {
                    // 2.封装结果对象 只需要 id 和 username
                    BankDetailUserListResp bankDetailUserListResp = new BankDetailUserListResp();
                    bankDetailUserListResp.setId(user.getId());
                    bankDetailUserListResp.setUserName(user.getUserName());
                    return bankDetailUserListResp;
                }).collect(Collectors.toList());

        return ApiResp.sucess(collect);
    }
}
